package apobates.gui.formatter.service;

import apobates.gui.formatter.packet.ResourceType;
import apobates.gui.formatter.reader.RemoteForm;
import apobates.gui.formatter.storage.*;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import org.reactfx.Change;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 最近记录执行器服务
 */
public class RecentExecutorService {
    // 最近记录执行器
    private GeneralRecentExecutor recentExecutor;
    // 最近记录
    private RemoteForm remoteForm;
    // 最近记录加载Loading(false开始|true结束)
    private Consumer<Boolean> recentLoadingFun;
    // 最近记录的编解码器
    private final static RecentRecordStringCodec recentRecordStringCodec = new RecentRecordStringCodec();
    // 支持的字符编码
    private final static String[] supportCharset = {"ISO-2022-CN", "BIG-5", "EUC-TW", "GB2312", "GBK", "GB18030", "UTF-8", "UTF-16", "UTF-16BE","UTF-32", "UTF-32BE", "ISO-8859-1", "WINDOWS-1252", "US-ASCII"};
    /**
     * 初始化
     * @param remoteForm 最近记录表单
     */
    public RecentExecutorService(RemoteForm remoteForm){
        // 记录最近的记录@20230402
        this.recentExecutor = JsonStorageRecentExecutor.getInstance();
        this.remoteForm = remoteForm;
    }

    /**
     * 初始化
     * @param remoteForm 最近记录表单
     * @param recentLoadingFun 最近记录加载状态消费函数. true结束|false开始
     */
    public RecentExecutorService(RemoteForm remoteForm, Consumer<Boolean> recentLoadingFun){
        this.recentExecutor = JsonStorageRecentExecutor.getInstance();
        this.remoteForm = remoteForm;
        this.recentLoadingFun = recentLoadingFun;
    }

    /**
     * 初始化
     */
    public RecentExecutorService(){
        // 记录最近的记录@20230402
        this.recentExecutor = JsonStorageRecentExecutor.getInstance();
        this.remoteForm = null;
    }

    /**
     * 初始化
     * @param recentLoadingFun 最近记录加载状态消费函数. true结束|false开始
     */
    public RecentExecutorService(Consumer<Boolean> recentLoadingFun){
        this.recentExecutor = JsonStorageRecentExecutor.getInstance();
        this.remoteForm = null;
        this.recentLoadingFun = recentLoadingFun;
    }
    /**
     * 初始化RemoteForm表单. 要求RemoteForm非空
     * 将历史记录填充到下拉框中
     * @deprecated
     */
    public void initialize(ComboBox<String> resourceURL) {
        Objects.requireNonNull(this.remoteForm);
        //
        Platform.runLater(()->{
            // 填充最近记录
            this.userRecentFillForm(ResourceType.FILE, resourceURL);
            // 事件侦听
            this.remoteForm.typeProperty().addListener((ObservableValue<? extends ResourceType> observableValue, ResourceType resourceType, ResourceType t1)-> {
                if(null!=t1){
                    this.userRecentFillForm(t1, resourceURL);
                }
            });
        });
    }

    /**
     * 将历史记录填到弹窗的ListView组件中
     * 取代ComboBox中存放最近记录
     * @param historyList
     * @param type
     */
    public void initialize(ListView<String> historyList, final ResourceType type) {
        // file://d:/x.json
        // http://ddd.x?encode=utf-8&timeout=8000

        List<String> list = recentExecutor.getType(type).stream().map(recentRecord -> {
            return recentRecordStringCodec.encode(recentRecord);
        }).collect(Collectors.toList());
        historyList.getItems().addAll(list);
    }
    /**
     * 加载所有最近记录
     * @return
     */
    public Set<RecentRecord> loadRecent() {
        return recentExecutor.getAll();
    }

    /**
     * 使用最近记录填充File菜单的menuRecentBtn
     * @param menuRecentBtn
     */
    public void fillRecentMenu(Menu menuRecentBtn){
        Set<RecentRecord> recentRecordSet = loadRecent();
        if(recentRecordSet.isEmpty()){
            menuRecentBtn.getItems().add(new MenuItem("暂无记录"));
        }else{
            List<MenuItem> recentRecentItem = recentRecordSet.stream().map(this.recentRecordMapper()).collect(Collectors.toList());
            menuRecentBtn.getItems().addAll(recentRecentItem);
        }
    }

    /**
     * 最近记录的重放执行. 现用于菜单中的最近记录
     * @param record
     */
    private void playbackRecentRecord(RecentRecord record){
        Objects.requireNonNull(record);
        // 20230508@开启loading...
        // 构建回放的请求对象
        RemoteForm _tempRF = new RemoteForm();
        _tempRF.setType(record.getType());
        _tempRF.setTimeout(record.getTimeout());
        _tempRF.setFileEncoding(record.getCharset());
        _tempRF.setFilePath(record.getPath());
        // 1.改用RemoteFormLoaderService来处理以便复用
        RemoteFormLoaderService remoteFormLoaderService = new RemoteFormLoaderService(_tempRF);
        // 3.侦听成功状态
        remoteFormLoaderService.stream().subscribe((Change<Boolean> booleanChange)-> {
            System.out.println("[RFLS][RES]service change success status:"+booleanChange.getNewValue());
            if(!booleanChange.getNewValue()){
                this.loadFail(_tempRF);
            }
        });
        // 4.侦听loading结束
        remoteFormLoaderService.loadedProperty().addListener((ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean t1)->{
            System.out.println("[RFLS][LOADED] loaded status listener:::");
            if(null != this.recentLoadingFun){
                System.out.println("[RFLS][LOADED] loaded consume function start::"+t1);
                // false开始
                // true结束
                this.recentLoadingFun.accept(t1);
            }
        });
        // 2.执行加载
        remoteFormLoaderService.load(this.recentLoadingFun);
    }
    private void loadFail(RemoteForm remoteForm){
        System.out.println("[RES]Load recent record fail. print record:::");
        System.out.println(remoteForm);
        // 删除无效的最近记录
        this.delete(remoteForm.getType(), remoteForm.getFilePath());
        //
        Alert noConTip = new Alert(Alert.AlertType.ERROR);
        noConTip.setContentText("最近记录目前无法访问");
        noConTip.show();
    }

    /**
     * 最近记录与MenuItem的映射函数
     * @return
     */
    public Function<RecentRecord, MenuItem> recentRecordMapper(){
        return (RecentRecord rrEle)->{
            // 创建菜单条目
            MenuItem temp = new MenuItem();
            temp.setUserData(rrEle);
            temp.setId(rrEle.hashCode()+"");
            temp.setText(rrEle.toMenuItemName());
            // 绑定点击事件
            temp.addEventHandler(ActionEvent.ACTION, (ActionEvent event)-> {
                System.out.println("[RES] recent menu click info::");
                MenuItem eventItem = (MenuItem)event.getSource();
                System.out.println(eventItem.getUserData());
                try {
                    this.playbackRecentRecord((RecentRecord) eventItem.getUserData());
                }catch (ClassCastException e){
                    System.out.println("[RES] recent menu userdata cast fail::");
                }catch (NullPointerException e1){
                    System.out.println("[RES] recent record is null");
                }
            });
            return temp;
        };
    }

    /**
     * 查询最近记录并填充@20230402
     * @deprecated
     * @param resourceType
     * @param resourceURL
     */
    private void userRecentFillForm(ResourceType resourceType, ComboBox<String> resourceURL){
        System.out.println("[JRC][RFF]find recent record type:"+resourceType.getNames());
        // 清空表单
        clearRemoteForm(resourceType);

        // 是否存在最近记录
        Optional<RecentRecord> lastURLRecord = recentExecutor.getLastByType(resourceType);
        if(lastURLRecord.isPresent()){
            // 填表单
            this.fillRemoteForm(lastURLRecord.get(), resourceURL);
        }else{
            System.out.println("[JRC][RFF]not find recent record for type:"+resourceType.getNames());
        }
    }

    /**
     * 填充候选的url
     * @deprecated
     * @param resourceURL
     */
    private void fillAutoURLItems(ComboBox<String> resourceURL){
        List<String> list = recentExecutor.getType(ResourceType.URL).stream().map(RecentRecord::getPath).collect(Collectors.toList());
        System.out.println("[RES]filter url recent record size:"+list.size());
        if(resourceURL.getItems().size() != list.size()) {
            resourceURL.getItems().addAll(list);
        }
    }

    /**
     * 从候选的url中挑选匹配的填充到ComboBox
     * @deprecated
     * @param currentWord
     * @param comboBox
     * @param list
     */
    private void filterCurrentWord(String currentWord, ComboBox<String> comboBox, List<String> list){
        List<String> filteredItems = new ArrayList<>();
        for (String item : list) {
            if (item.toLowerCase().startsWith(currentWord.toLowerCase())) {
                filteredItems.add(item);
            }
        }
        comboBox.setItems(FXCollections.observableArrayList(filteredItems));
    }
    // 填充最近记录时，当切换资源类型时：不保留上次的旧痕@20230402
    private void clearRemoteForm(ResourceType resourceType){
        Objects.requireNonNull(this.remoteForm);
        //
        remoteForm.reset(resourceType);
        System.out.println("[JRC][CRF]clear CTL component value");
    }

    /**
     * 使用最近记录填充表单@20230402
     * @deprecated
     * @param recentRecord
     * @param comboBox
     */
    private void fillRemoteForm(RecentRecord recentRecord, ComboBox<String> comboBox){
        System.out.println("[JRC][FRF]use argument recent record:");
        System.out.println(recentRecord);
        //
        Objects.requireNonNull(this.remoteForm);
        // 资源类型
        this.remoteForm.setType(recentRecord.getType());
        // 资源路径
        this.remoteForm.setFilePath(recentRecord.getPath());
        // 字符集
        this.remoteForm.setFileEncoding(recentRecord.getCharset());
        // 超时
        this.remoteForm.setTimeout(recentRecord.getTimeout());
        // System.out.println("[JRC][FRF]charset:"+rourceCharset.getValue()+", timeout:"+requestTime.getValue()+", path:"+recentRecord.getPath());
        if(recentRecord.getType() == ResourceType.URL){
            this.fillAutoURLItems(comboBox);
        }
    }

    /**
     * 记录最近记录. 要求RemoteForm非空
     */
    public void cache(){
        Objects.requireNonNull(this.remoteForm);
        //
        this.recentExecutor.replace(
                new RecentRecord(
                        this.remoteForm.getFilePath(),
                        this.remoteForm.getType(),
                        remoteForm.getFileEncoding(),
                        remoteForm.getTimeout()));
    }

    /**
     * 记录指定的最近记录
     * @param record
     */
    public void cache(RecentRecord record){
        Objects.requireNonNull(record);
        //
        this.recentExecutor.replace(record);
    }

    /**
     * 将内存中的最近记录持久化
     */
    public void persiste(){
        this.recentExecutor.persiste();
    }

    /**
     * 删除指定的类型的最近记录
     * @param resourceType Json资源类型
     * @param resourcePath 资源路径
     * @return 删除成功返回true
     */
    public boolean delete(ResourceType resourceType, String resourcePath){
        return this.recentExecutor.delete(resourceType, resourcePath);
    }

    /**
     * 返回最近记录编解码器
     * @return
     */
    public static RecentRecordCodec<String> getRecentRecordCodec(){
        return recentRecordStringCodec;
    }

    /**
     * 返回支持的JSON字符集
     * @return
     */
    public static String[] getSupportCharset(){
        return supportCharset;
    }
}
